package com.yanfan.jksh;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class JkshUtil {

    final static String SEPARATOR = "\\*";
    final static String BODY_SEPARATOR = ",";

    @Getter
    @AllArgsConstructor
    enum Type {

        // 链路保持/心跳
        /**
         * 链路保持
         * 终端发送:
         * [DW*YYYYYYYYYYYYYYY*LEN*KA,日期，步数,翻滚次数,电量百分数,车载里程数(km)]
         * 实例:[DW*334588000000156*0014*KA,120414,50,100,100,100.12]
         * 平台回复:
         * [DW*YYYYYYYYYYYYYYY*LEN*KA]
         */
        KA("KA", "链路保持", true),

        /**
         * 位置数据上报
         * 终端发送:
         * 实例:
         * [DW*334588000000156*00CD*UD,160918,025723,A,22.570733,N,113.8626083,E,0.00,249.5,0.0,6,
         * 100,60,0,00000010,7,255,460,1,9529,21809,158,9529,63555,133,9529,63554,129,9529,21405,1
         * 26,9529,21242,124,9529,21151,120,9529,63556,119,0]
         * 说明：
         * 数据内容:
         * UD,命令号
         * 160918,日期（日月年）（0 时区），表示 0 时区的二零一八年九月十六号
         * 025723,时间（时分秒）（0 时区），表示 0 时区的两点五十七分二十三秒
         * A,gps 定位有效
         * 22.570733,纬度
         * N,纬度标识
         * 113.8626083,经度
         * E,经度标识
         * 0.00,速度
         * 249.5,方向
         * 0.0,海拔
         * 6,卫星个数
         * 100,gsm 信号强度
         * 60,电量
         * 0,计步数
         * 00000010,终端状态，数据为 16 进制，解析成二进制为 0000 0000 0000 0000 0000 0000 0001 0000
         * 前面 4 个字节表示状态，后面 4 个字节表示报警，数据中第 4 位为 1，对照文档最后的数据解析，表
         * 示手表静止状态。详细可参看文档最后部分。
         * 7,基站个数
         * 255,460,1,9529,21809,158,9529,63555,133,9529,63554,129,9529,21405,126,9529,21242,124,95
         * 29,21151,120,9529,63556,119,基站信息
         * 0,WiFi 个数
         * 平台不需要回复
         * 说明:终端按照设定间隔上报位置和状态信息,不需要平台回复.
         */
        UD("UD", "位置数据上报", false),
        UD2("UD2", "盲点补传数据", false),
        UD_LTE("UD_LTE", "4G电信上报指令", false),
        UD_CDMA("UD_CDMA", "4G电信上报指令", false),
        UD_WCDMA("UD_WCDMA", "3G电信上报指令", false),
        UD_TDSCDMA("UD_TDSCDMA", "3G电信上报指令", false),

        /**
         * 报警数据上报
         * 终端发送:
         * [DW*YYYYYYYYYYYYYYY*LEN*AL,位置数据(见附录一)]
         * 实例:
         * [DW*334588000000156*00CD*AL,160918,064153,A,22.570512,N,113.8623267,E,0.00,154.8,0.0,11,
         * 100,100,0,0,00100018,7,0,460,1,9529,21809,155,9529,21242,132,9529,21405,131,9529,63554,
         * 131,9529,63555,130,9529,63556,118,9529,21869,116,0,12.4]
         * 平台回复:
         * [DW*YYYYYYYYYYYYYYY*LEN*AL]
         */
        AL("AL", "报警数据上报", true),
        // 获取天气
        WT("WT", "", false),
        WG("WG", "", false),
        DLT("DLT", "", false),
        ICCID("ICCID", "", false),
        CR("CR", "", false),
        FACTORY("FACTORY", "", false),
        POWEROFF("POWEROFF", "", false),
        RESET("RESET", "", false),
        CALL("CALL", "", false),
        FIND("FIND", "", false),
        UPLOAD("UPLOAD", "", false),
        CENTER("CENTER", "", false),
        SOS("SOS", "", false),
        SOSSMS("SOSSMS", "", false),
        LOWBAT("LOWBAT", "", false),
        VERNO("VERNO", "", false),
        REMOVE("REMOVE", "", false),
        PEDO("PEDO", "", false),
        SILENCETIME2("SILENCETIME2", "", false),
        SLEEPTIME("SLEEPTIME", "", false),
        REMIND("REMIND", "", false),
        REMIND_TAG("REMIND_TAG", "", false),
        REMIND_CH_MEDICINE("REMIND_CH_MEDICINE", "", false),
        REMIND_CH_SLEEP("REMIND_CH_SLEEP", "", false),
        REMIND_CH_WAKEUP("REMIND_CH_WAKEUP", "", false),
        REMIND_CH_DRINK("REMIND_CH_DRINK", "", false),
        REMIND_CH_MEDICINE2("REMIND_CH_MEDICINE2", "", false),
        REMIND_CH_SIT("REMIND_CH_SIT", "", false),
        PHL("PHL", "", false),
        WLKEY("WLKEY", "", false),

        profile("profile", "", false),
        FALLDOWN("FALLDOWN", "", false),
        BOOTOFF("BOOTOFF", "", false),
        KEYBRD("KEYBRD", "", false),
        hrtstart("hrtstart", "", false),

        /**
         * 终端心率上传<br>
         * 终端上传：<br>
         * [DW*334588000000156*len*heart,x]<br>
         * x 为每分钟心率数据。<br>
         * 实例：[DW*334588000000156*len*heart,100]<br>
         * 代表终端的心率为：100 次/分钟<br>
         * 平台回复：<br>
         * [DW*334588000000156*0005*heart]<br>
         */
        heart("heart", "终端心率上传", true),
        wdstart("wdstart", "", false),
        /**
         * 上传体温数据<br>
         * 终端上传：<br>
         * [DW*YYYYYYYYYYYYYYY*LEN*temp,X.X]<br>
         * X.X: 当前测到温度值。<br>
         * 实例：[DW*334588000000156*0009*temp,36.2]<br>
         * 代表终端的温度为：36.2<br>
         * 平台回复：<br>
         * [DW*334588000000156*0004*temp]<br>
         */
        temp("temp", "上传体温数据", true),
        bldstart("bldstart", "", false),

        /**
         * 终端发送[DW*YYYYYYYYYYYYYYY*LEN*blood,x,y]<br>
         * x 是收缩压（高压）<br>
         * y 是舒张压（低压）<br>
         * 28 示例[DW*334588000000156*000C*blood,150,70]<br>
         * 平台回复：<br>
         * [DW*334588000000156*0005*blood]<br>
         */
        blood("blood", "上传血压数据", true),
        oxstart("oxstart", "", false),
        /**
         * 终端发送[DW*YYYYYYYYYYYYYYY*LEN*oxygen,x]<br>
         * x 表示血氧饱和度<br>
         * 示例[DW*334588000000156*0009*oxygen,15]<br>
         * 平台回复：<br>
         * [DW*334588000000156*0006*oxygen]<br>
         */
        oxygen("oxygen", "上传血氧数据", true),
        /**
         * 血压心率
         * */
        bphrt("bphrt", "血压心率上传", true),

        TK("TK", "", false),
        TKS("TKS", "发送语音", true),
        TKQ("TKQ", "", false),
        MESSAGE("MESSAGE", "", false),
        appvoicemsg("appvoicemsg", "", false),
        devvoicemsg("devvoicemsg", "", false),
        ppsrvvoicemsg("ppsrvvoicemsg", "", false),
        ppdevvoicemsg("ppdevvoicemsg", "", false),
        srvtextmsg("srvtextmsg", "", false),
        MFCODE_REQ("MFCODE_REQ", "", false),
        MFCODE_MATCH("MFCODE_MATCH", "", false),
        ppfriends("ppfriends", "", false),
        MFCODE_FRIEND("MFCODE_FRIEND", "", false),
        TIMETABLE("TIMETABLE", "", false),
        SYNCPHL("SYNCPHL", "", false),
        STRANGERCALL("STRANGERCALL", "", false),
        AUTOANSWER("AUTOANSWER", "", false),
        DEV_BIND_REQ("DEV_BIND_REQ", "", false),
        DEV_BIND("DEV_BIND", "", false),
        DEVMESSAGESWITCH("DEVMESSAGESWITCH", "", false),
        DEVMESSAGE("DEVMESSAGE", "", false),
        BOOTOFFQ("BOOTOFFQ", "", false),
        APPDOWNLOADURLREQ("APPDOWNLOADURLREQ", "", false),
        APPDOWNLOADURL("APPDOWNLOADURL", "", false),
        OTHER("OTHER", "其他", false);
        private final String code;
        private final String title;
        private final boolean isReply;

        public static Type getType(String cmd) {
            for (Type value : values()) {
                if (Objects.equals(cmd, value.code)) {
                    return value;
                }
            }
            return OTHER;
        }
    }

    public static JSONObject getData(String body) {
        String[] bodys = body.split(BODY_SEPARATOR);
        JSONObject data = JSONObject.of();
        String cmd = bodys[0];
        data.put("cmd", cmd);
        Type type = Type.getType(cmd);
        // SOS、心率、血压、血氧、体温、语音、跌倒、定位（位置）、低电、报警数据、是否佩戴相关的
        switch (type) {
            // 心跳
            case KA: {
                // DW*334588000000156*001B*KA,120414,50,100,100,100.12
                // 心跳日期
                String date = bodys[1];
                data.put("heartbeatDate", date);
                // 步数
                String stepCount = bodys[2];
                data.put("stepCount", stepCount);
                // 翻滚次数
                String tumblesCount = bodys[3];
                data.put("tumblesCount", tumblesCount);
                // 电量百分数
                String electricity = bodys[4];
                data.put("electricity", electricity);
                if (bodys.length > 5) {
                    // 车载里程数(km)
                    String carMileageKm = bodys[5];
                    data.put("carMileageKm", carMileageKm);
                }
                break;
            }
            // 定位
            case UD:
            case UD2:
            case UD_LTE:
            case UD_CDMA:
            case UD_WCDMA:
            case UD_TDSCDMA: {
                // DW*334588000000156*00C6*UD,160918,025723,A,22.570733,N,113.8626083,E,0.00,249.5,0.0,6,100,60,0,00000010,7,255,460,1,9529,21809,158,9529,63555,133,9529,63554,129,9529,21405,126,9529,21242,124,9529,21151,120,9529,63556,119,0
                data = parseLocationInfo(bodys);
                break;
            }
            // 告警
            case AL: {
                // DW*334588000000156*00CD*AL,160918,064153,A,22.570512,N,113.8623267,E,0.00,154.8,0.0,11,100,100,0.0,00100018,7,0,460,1,9529,21809,155,9529,21242,132,9529,21405,131,9529,63554,131,9529,63555,130,9529,63556,118,9529,21869,116,0,12.4
                data = parseLocationInfo(bodys);
                // 剩余结尾处的12.4不明所以，无法解析完善
                break;
            }
            // 心率
            case heart:
            case hrtstart: {
                // DW*334588000000156*len*heart,100
                // 分钟/次数
                String heart = bodys[1];
                data.put("heart", heart);
                break;
            }
            // 上传血压数据
            case blood: {
                // DW*334588000000156*000C*blood,150,70
                // 收缩压
                String bloodx = bodys[1];
                data.put("bloodx", bloodx);
                // 舒张压
                String bloody = bodys[2];
                data.put("bloody", bloody);
                break;
            }
            // 上传血氧数据
            case oxygen: {
                // DW*334588000000156*0009*oxygen,15
//                String oxygen = bodys[1];
//                data.put("oxygen", oxygen);
                String oxygen = bodys[2];
                data.put("oxygen", oxygen);
                break;
            }
            case bphrt: {
                // DW*334588000000156*0009*oxygen,15
                // 收缩压
                String bloodx = bodys[1];
                data.put("bloodx", bloodx);
                // 舒张压
                String bloody = bodys[2];
                data.put("bloody", bloody);
                // 心率
                String heart = bodys[3];
                data.put("heart", heart);
                // 身高
                String height = bodys[4];
                data.put("height", height);
                // 性别
                String sex = bodys[5];
                data.put("sex", sex);
                // 年龄
                String age = bodys[6];
                data.put("age", age);
                // 体重
                String weight = bodys[7];
                data.put("weight", weight);
                break;
            }
            // 上传体温数据
            case temp: {
                // DW*334588000000156*0009*temp,36.2
                String temp = bodys[1];
                data.put("temp", temp);
                break;
            }
            case FALLDOWN: {
                // [3G*YYYYYYYYYY*LEN*FALLDOWN,X,Y]
                // 跌倒状态
                String falldown = bodys[1];
                data.put("falldown", falldown);
                String falldowncall = bodys[2];
                data.put("falldowncall", falldowncall);
                break;
            }

            case TKQ: {
                break;
            }
            // 语音
            case TKS: {
                break;
            }
        }
        return data;
    }

    /**
     * [DW*334588000000156*00CD*UD,160918,025723,A,22.570733,N,113.8626083,E,0.00,249.5,0.0,6,100,60,0,00000010,
     * 7,255,460,1,
     * 9529,21809,158,
     * 9529,63555,133,
     * 9529,63554,129,
     * 9529,21405,126,
     * 9529,21242,124,
     * 9529,21151,120,
     * 9529,63556,119,
     * 0]
     */
    private static JSONObject parseLocationInfo(String[] bodys) {
        int currIndex = 0;
        JSONObject data = JSONObject.of();
        String cmd = bodys[currIndex++];
        data.put("cmd", cmd);
        // 160918,日期（日月年）（0 时区），表示 0 时区的二零一八年九月十六号
        String date = bodys[currIndex++];
        data.put("date", date);
        // 025723,时间（时分秒）（0 时区），表示 0 时区的两点五十七分二十三秒
        String time = bodys[currIndex++];
        data.put("time", time);
        // A,gps 定位有效
        String gpsvalid = bodys[currIndex++];
        data.put("gpsvalid", gpsvalid);
        // 22.570733,纬度
        String latitude = bodys[currIndex++];
        data.put("latitude", latitude);
        // N,纬度表示
        String latitudeKey = bodys[currIndex++];
        data.put("latitudeKey", latitudeKey);
        // 113.8626083,经度
        String longitude = bodys[currIndex++];
        data.put("longitude", longitude);
        // E,经度表示
        String longitudeKey = bodys[currIndex++];
        data.put("longitudeKey", longitudeKey);
        // 0.00,速度
        String speed = bodys[currIndex++];
        data.put("speed", speed);
        // 249.5,方向
        String direction = bodys[currIndex++];
        data.put("direction", direction);
        // 0.0,海拔
        String elevation = bodys[currIndex++];
        data.put("elevation", elevation);
        // 6,卫星个数
        String satellitesCount = bodys[currIndex++];
        data.put("satellitesCount", satellitesCount);
        // 100,gsm 信号强度
        String gsm = bodys[currIndex++];
        data.put("gsm", gsm);
        // 60,电量
        String electricity = bodys[currIndex++];
        data.put("electricity", electricity);
        // 0,计步数
        String step = bodys[currIndex++];
        data.put("step", step);
        // 0,翻滚次数
        String tumblesCount = bodys[currIndex++];
        data.put("tumblesCount", tumblesCount);
        // 0000 0010,终端状态，数据为 16 进制，
        // 解析成二进制为
        // 0000 0000 0000 0000
        // 0000 0000 0001 0000
        // 前面 4 个字节表示状态，
        // 后面 4 个字节表示报警，数据中第 4 位为 1，
        // 对照文档最后的数据解析，表示手表静止状态。详细可参看文档最后部分。
        String endpointStatus = bodys[currIndex++];
        data.put("endpointStatus", endpointStatus);

        JSONObject status = parseStatus(endpointStatus);
        data.putAll(status);

        // 7,基站个数
        int baseStationsCount = Integer.parseInt(bodys[currIndex++]);
        data.put("baseStationsCount", baseStationsCount);
        if (baseStationsCount > 0) {
            // 255, 连接基站ta
            String station = bodys[currIndex++];
            data.put("station", station);
            // 460, MCC 国家码
            String MCC = bodys[currIndex++];
            data.put("MCC", MCC);
            // 1, MNC 网号
            String MNC = bodys[currIndex++];
            data.put("MNC", MNC);
            // 9529,21809,158,  连接基站位置区域码 连接基站编号 连接基站信号强度
            // 9529,63555,133,  附近基站 1 位置区域码 附近基站 1 编号 附近基站 1 信号强度
            // 9529,63554,129,  附近基站 2 位置区域码 附近基站 2 编号 附近基站 2 信号强度
            // 9529,21405,126,  附近基站 3 位置区域码 附近基站 3 编号 附近基站 3 信号强度
            // 9529,21242,124,  附近基站 4 位置区域码 附近基站 4 编号 附近基站 4 信号强度
            // 9529,21151,120,  附近基站 5 位置区域码 附近基站 5 编号 附近基站 5 信号强度
            // 9529,63556,119,  附近基站 6 位置区域码 附近基站 6 编号 附近基站 6 信号强度
            JSONArray arr = JSONArray.of();
            for (int i = 0; i < baseStationsCount; i++) {
                arr.add(JSONObject.of(
                        "station", bodys[currIndex++],
                        "localhost", bodys[currIndex++],
                        "signal", bodys[currIndex++]
                ));
            }
            // 基站信息
            data.put("baseStationsInfo", arr.toJSONString());
        }
        // 0,WiFi 个数
        int wifiCount = Integer.parseInt(bodys[currIndex++]);
        data.put("wifiCount", wifiCount);
        if (wifiCount > 0) {
            JSONArray arr = JSONArray.of();
            // FIXME 没有实际的数据示例 此处待完善
            //  Wifi 1 名字 rrr 第 1 个 wifi 信息名字
            //  Wifi 1 MAC 地址 1c:fa:68:13:a 5:b4  第 1 个 wifi MAC 地址
            //  Wifi 1 信号强度 -61 第 1 个 wifi 信号强度
            for (int i = 0; i < wifiCount; i++) {
                arr.add(JSONObject.of(
                        "wifiName", bodys[currIndex++],
                        "wifiMac", bodys[currIndex++],
                        "wifiSignal", bodys[currIndex++]
                ));
            }
            // 基站信息
            data.put("wifiInfo", arr.toJSONString());
        }
        return data;
    }


    private static final Map<Integer, String> STATUS_MAP = new HashMap<>();
    private static final Map<Integer, String> ALARM_MAP = new HashMap<>();

    static {
        // 初始化状态位映射
        STATUS_MAP.put(0, "低电状态");
        STATUS_MAP.put(1, "出围栏状态（目前没用到）");
        STATUS_MAP.put(2, "进围栏状态（目前没用到）");
        STATUS_MAP.put(3, "手环戴上取下状态");
        STATUS_MAP.put(4, "手表运行静止状态");
        // 初始化报警位映射
        ALARM_MAP.put(16, "SOS报警");
        ALARM_MAP.put(17, "低电报警");
        ALARM_MAP.put(18, "出围栏报警（目前没用到）");
        ALARM_MAP.put(19, "进围栏报警（目前没用到）");
        ALARM_MAP.put(20, "手环拆除报警");
        ALARM_MAP.put(21, "跌倒报警");
        ALARM_MAP.put(22, "心率异常报警");
        ALARM_MAP.put(26, "落水报警");
    }

    public static JSONObject parseStatus(String hexStr) {
        JSONObject status = JSONObject.of();
        // 处理输入字符串：移除空格并补零至8位
        hexStr = hexStr.replaceAll("\\s+", "").toUpperCase();
        hexStr = String.format("%8s", hexStr).replace(' ', '0');

        try {
            long value = Long.parseLong(hexStr, 16);

            // 分割高16位（报警）和低16位（状态）
            int alarmBits = (int) ((value >> 16) & 0xFFFF);
            int statusBits = (int) (value & 0xFFFF);
            int runningStatus = 0;
            int alarmStatus = 0;

            // 解析状态位（低16位）
            for (int i = 0; i < 16; i++) {
                if ((statusBits & (1 << i)) != 0) {
                    runningStatus = i;
                    break;
                }
            }

            // 解析报警位（高16位）
            for (int i = 0; i < 16; i++) {
                if ((alarmBits & (1 << i)) != 0) {
                    alarmStatus = 16 + i;
                }
            }
            status.put("runningStatus", runningStatus);
            status.put("runningStatusMsg", STATUS_MAP.getOrDefault(runningStatus, "未知运行状态"));
            status.put("alarmStatus", alarmStatus);
            status.put("alarmStatusMsg", ALARM_MAP.getOrDefault(alarmStatus, "未知告警状态"));
        } catch (NumberFormatException e) {
            System.out.println("无效的十六进制字符串: " + hexStr);
        }
        return status;
    }




    public static void main(String[] args) {

        // 0000 0000 0010 0000  左
        // 0000 0000 0001 0000  右
//        String input = "00200010";

        // 0000 0000 0001 0000  左
        // 0000 0000 0001 1000  右
        String input = "00100018";
        parseStatus(input);

        String baowen = "UD,120118,070625,A,22.570720,N,113.8620167,E,0.00,188.6,0.0,9,100,51,14188,0,00000010,6,255,460,0,9360,5081,156,9360,4081,129,9360,4151,128,9360,5082,127,9360,4723,122,9360,4082,120,5,buyaoxialian,a0:c5:f2:b0:7.4:d0,-34,3gtc-5g,92:76:9f:48:4f:20,-48,726,38:37:8b:7:cf:99,-54,3gtc,d0:ae:ec:96:10:54,-63,ceshi,d0:ae:ec:96:10:55,-64,22.4";
        JSONObject obj = JkshUtil.getData(baowen);
        System.out.println(obj);

    }
}
